#pragma once
#include "lockGuard.hpp"
#include "thread.hpp"
#include <vector>
#include <string>
#include <queue>
#include <iostream>
#include <unistd.h>
#include "log.hpp"

const int g_thread_num = 3;

template <class T>
class ThreadPool
{
private:
    std::vector<Thread *> _threads;
    int _num;               //线程池中线程的数量
    std::queue<T> _taskQueue;//任务队列
    pthread_mutex_t _mutex; // 互斥锁
    pthread_cond_t _cond;   // 条件变量

    static ThreadPool<T>* _threadPoolPtr;//单例对象指针
    static pthread_mutex_t _mtx;//单例对象的互斥锁

private:
    //构造函数私有化
    ThreadPool(int thread_num = g_thread_num) : _num(thread_num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        for (int i = 0; i < _num; ++i)
        {
            _threads.push_back(new Thread(i, routine, this));
        }
    }

    //防拷贝
    ThreadPool(const ThreadPool<T>& threadpool) = delete;
    ThreadPool<T> operator=(const ThreadPool<T>& threadpool) = delete;

public:
    pthread_mutex_t *getMutex()
    {
        return &_mutex;
    }

    void waitCond()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

public:
    //全局访问点
    static ThreadPool<T>* getThreadPool(int num = g_thread_num)
    {
        if(_threadPoolPtr == nullptr)
        {
            pthread_mutex_lock(&_mtx);
            if(_threadPoolPtr == nullptr)
            {
                _threadPoolPtr = new ThreadPool<T>(num);
            }
            pthread_mutex_unlock(&_mtx);
        }
        return _threadPoolPtr;
    }

    //启动线程
    void run()
    {
        for (auto &it : _threads)
        {
            it->start();
            //std::cout << it->name() << " 启动成功" << std::endl;
            logMessage(NORMAL,"%s %s",it->name().c_str(),"启动成功 ");
        }
    }

    T getTask()
    {
        T task = _taskQueue.front();
        _taskQueue.pop();
        return task;
    }

    // 消费过程
    //将routine函数设为静态,是因为routine是作为线程例程函数的,所以如果不讲routine设为静态,routine函数的参数就会多出一个this指针
    static void *routine(void *args)
    {
        ThreadData *td = (ThreadData *)args;
        ThreadPool<T> *tp = (ThreadPool<T> *)td->args_;
        while (true)
        {
            T task;
            {
                lockGuard lock(tp->getMutex());//构造加锁,出作用域解锁
                while (tp->_taskQueue.empty())
                    tp->waitCond();

                // 读取任务
                task = tp->getTask(); // 任务队列是共享的-> 将任务从共享，拿到自己的私有空间
            }
            // 处理任务
            task(td->name_);

            // sleep(1);
        }
    }

    // 生产过程
    void pushTask(const T &task)
    {
        lockGuard lock(&_mutex);
        _taskQueue.push(task);
        pthread_cond_signal(&_cond);
    }

    ~ThreadPool()
    {
        for (auto &it : _threads)
        {
            it->join();
            delete it;
        }

        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
};

template <class T>
ThreadPool<T>* ThreadPool<T>::_threadPoolPtr = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::_mtx = PTHREAD_MUTEX_INITIALIZER;